﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using HRProject.Code.DTO;
using System.Collections.Generic;
using HRProject.Code.Common;

namespace HRProject.Code.DAO
{
    public class AssetTypeDAO : BaseDAO
    {
        public AssetTypeDAO()
            : base ()
        {
        }

        public BLAssetType getRootAssetType()
        {
            List<BLAssetType> assetTypes = select();
            BLAssetType root = arrangeAssetType(assetTypes);
            return root;
        }

        private List<BLAssetType> select()
        {
            List<BLAssetType> result = new List<BLAssetType>();
            List<BaseCondition> condition = new List<BaseCondition>();
            condition.Add(new BaseCondition("@id", Guid.Empty, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", string.Empty, ParameterDirection.Input));
            condition.Add(new BaseCondition("@parentId", Guid.Empty, ParameterDirection.Input));
            DataTable data = select("usp_searchAssetTypes", condition);
            for (int i = 0; i < data.Rows.Count; i++)
            {
                BLAssetType assetType = new BLAssetType();
                assetType.Id = (Guid)data.Rows[i]["AssetTypeId"];
                assetType.Name = (string)data.Rows[i]["AssetTypeName"];
                assetType.Description = (string)data.Rows[i]["Description"];
                assetType.Parent = new BLAssetType();
                assetType.Parent.Id = (Guid)data.Rows[i]["ParentAssetTypeId"];
                assetType.DataSignature = (long)data.Rows[i]["DataSignature"];
                assetType.CreateDate = (DateTime)data.Rows[i]["CreateDate"];
                assetType.CreateUserId = (Guid)data.Rows[i]["CreateUserId"];
                assetType.UpdateDate = (DateTime)data.Rows[i]["UpdateDate"];
                assetType.UpdateUserId = (Guid)data.Rows[i]["UpdateUserId"];
                result.Add(assetType);
            }
            return result;
        }

        public List<BLAssetType> search(BLAssetType filter)
        {
            List<BLAssetType> result = new List<BLAssetType>();
            List<BaseCondition> condition = new List<BaseCondition>();
            condition.Add(new BaseCondition("@id", filter.Id,ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", filter.Name,ParameterDirection.Input));
            condition.Add(new BaseCondition("@parentId", filter.Parent.Id,ParameterDirection.Input));
            DataTable data = select("usp_searchAssetTypes", condition);
            for (int i = 0; i < data.Rows.Count; i++)
            {
                BLAssetType assetType = new BLAssetType();
                assetType.Id = (Guid)data.Rows[i]["AssetTypeId"];
                assetType.Name = (string)data.Rows[i]["AssetTypeName"];
                assetType.Description = (string)data.Rows[i]["Description"];
                assetType.Parent = new BLAssetType();
                assetType.Parent.Id = (Guid)data.Rows[i]["ParentAssetTypeId"];
                assetType.Parent.Name = (string)data.Rows[i]["ParentAssetTypeName"];
                assetType.DataSignature = (long)data.Rows[i]["DataSignature"];
                assetType.CreateDate = (DateTime)data.Rows[i]["CreateDate"];
                assetType.CreateUserId = (Guid)data.Rows[i]["CreateUserId"];
                assetType.UpdateDate = (DateTime)data.Rows[i]["UpdateDate"];
                assetType.UpdateUserId = (Guid)data.Rows[i]["UpdateUserId"];
                result.Add(assetType);
            }
            return result;
        }

        private BLAssetType arrangeAssetType(List<BLAssetType> types)
        {
            BLAssetType result = new BLAssetType();
            result.Name = "General";
            foreach (BLAssetType type in types)
            {
                bind(result, type);
            }
            return result;
        }

        private bool bind(BLAssetType ancestor, BLAssetType type)
        {
            if (ancestor.Id == type.Parent.Id)
            {
                int index = 0;
                for (int i = 0; i < ancestor.Children.Count; i++)
                {
                    if (type.Name.ToLower().CompareTo(ancestor.Children[i].Name.ToLower()) > 0)
                    {
                        index = i+1;
                        break;
                    }
                }
                ancestor.Children.Insert(index, type);
                type.Parent = ancestor;
                return true;
            }
            foreach (BLAssetType child in ancestor.Children)
            {
                if (bind(child, type))
                {
                    return true;
                }
            }
            return false;
        }

        public int Insert(BLAssetType assetType, ref int errorCode)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name",assetType.Name,ParameterDirection.Input));
            condition.Add(new BaseCondition("@description", assetType.Description, ParameterDirection.Input));
            condition.Add(new BaseCondition("@parentId", assetType.Parent.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId,ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature",assetType.DataSignature,ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode",errorCode,ParameterDirection.Output));
            int result = update("usp_AddAssetType", condition);
            errorCode = (int)condition[condition.Count - 1].ParamValue;
            return result;
        }

        public int update(BLAssetType assetType)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            int errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", assetType.Name, ParameterDirection.Input));
            condition.Add(new BaseCondition("@description", assetType.Description, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId, ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", assetType.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_updateAssetType", condition);
            return result;
        }

        public int delete(BLAssetType assetType)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            int errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId, ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", assetType.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_deleteAssetType", condition);
            return result;
        }

        public BLAssetType BuildTree(List<BLAssetType> list)
        {
            BLAssetType result = new BLAssetType();
            result.Id = Guid.Empty;
            result.Name = ContentProvider.GetString("GeneralAssetType");

            List<BLAssetType> tempList = new List<BLAssetType>();
            tempList.AddRange(list);

            while (tempList.Count > 0)
            {
                for (int i = 0; i < tempList.Count; i++)
                {
                    if (tempList[i].Id.Equals(result.Id))
                    {
                        result.Name = tempList[i].Name;
                        tempList.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        BLAssetType parent = FindParent(result, tempList[i].Parent.Id);
                        if (parent != null)
                        {
                            tempList[i].Parent = parent;
                            parent.Children.Add(tempList[i]);
                            tempList.RemoveAt(i);
                            i--;
                        }
                        else
                        {
                            tempList.Add(tempList[i]);
                            tempList.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }

            return result;
        }

        private BLAssetType FindParent(BLAssetType node, Guid parentId)
        {
            if (parentId.Equals(node.Id))
            {
                return node;
            }
            foreach (BLAssetType child in node.Children)
            {
                BLAssetType temp = FindParent(child, parentId);
                if (temp != null)
                {
                    return temp;
                }
            }
            return null;
        }

        public int Rename(BLAssetType assetType, ref int errorCode)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", assetType.Name, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId, ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", assetType.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_RenameAssetType", condition);
            errorCode = (int)condition[condition.Count - 1].ParamValue;
            return result;
        }

        public int Move(BLAssetType assetType, ref int errorCode)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@parentId", assetType.Parent.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId, ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", assetType.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_MoveAssetType", condition);
            errorCode = (int)condition[condition.Count - 1].ParamValue;
            return result;
        }

        public int Delete(BLAssetType assetType, ref int errorCode)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            errorCode = 0;
            condition.Add(new BaseCondition("@id", assetType.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", BLAuthentication.CurrentUserId, ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", assetType.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_DeleteAssetType", condition);
            errorCode = (int)condition[condition.Count - 1].ParamValue;
            return result;
        }
    }
}
